home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Info-Mac 3
/
Info_Mac_1994-01.iso
/
Development
/
4th Dimension
/
Relate Selection Source
< prev
Wrap
Text File
|
1993-12-20
|
6KB
|
166 lines
Here are two approaches to the RelateSelection procedure, which
generates a selection of records in a file based on a selection of
records in a related file. In v3 JOIN and PROJECT SELECTION replace
this method, though it still has some advantages.
Procedure RelateSelection (enhanced) 5/20/91
______________________________________________
This is an enhanced version of the recently uploaded RelateSelection. It's
a little faster overall, and uses arrays to speed up searches on large
base file selections.
This code will find the records in a file (SearchFile) which are related
to a selection of records in another file (BaseFile). The files can be
related one to many, many to one or without drawn relations at all (this
last is great for creating small indexes (lookup files) for large files).
So far, when compiled, the code appears to be faster than any other method.
Regarding the array technique, be aware that it requires 4 bytes of RAM
for each record in the selection.
The progress messages are based on Tech Note No. 206, "Displaying a Custom
Progress Indicator".
______________________________________________
`RelateSelection - enhanced
`Based on original code by Tony Ringsmuth 6/90
`Modified 5/91 by Bob Keleher 70451,510 - with contributions
`and suggestions by Lincoln Stoller and other members of the Acius Forum.
`$1 = >>Search field
`$2 = >>Base field
C_POINTER($SearchFile;$BaseFile)
C_LONGINT($Max;$i;$j;$BaseRecs;$LastJ)
$SearchFile:=File(File($1)) `get pointer to file from field pointer
$BaseFile:=File(File($2))
$BaseRecs:=Records in selection($BaseFile>>)
$Max:=256 `built searches don't like more than 256
Case of
: ($BaseRecs=0)
CREATE EMPTY SET($SearchFile>>;"Related")
USE SET("Related")
CLEAR SET("Related")
: ($BaseRecs<=$Max)
`Setup progress indicator here e.g. Progress($BaseRecs;"Your
message")
FIRST RECORD($BaseFile>>)
SEARCH($SearchFile>>;$1>>=$2>>;*)
`Progress(1) `update thermometer
For ($i;2;$BaseRecs)
NEXT RECORD($BaseFile>>)
SEARCH($SearchFile>>; | $1>>=$2>>;*)
`Progress(1) `update thermometer
End for
SEARCH($SearchFile>>)
`Progress(0) `close progress indicator window
Else
`Setup progress indicator here e.g.
Progress(($BaseRecs\$Max)+1;"Your message")
$LastJ:=(($BaseRecs\$Max)*$Max)+1 `value of $j at last outer loop
CREATE EMPTY SET($SearchFile>>;"Related")
If (Type($2>>)=8) | (Type($2>>)=9) `integer or LongInt
ARRAY LONGINT(vLIntArray;0)
SELECTION TO ARRAY($2>>;vLIntArray)
For ($j;1;$BaseRecs;$Max)
SEARCH($SearchFile>>;$1>>=vLIntArray{$j};*)
If ($j=$LastJ) `last outer loop
$Max:=$BaseRecs-$j+1
End if
For ($i;$j+1;$j-1+$Max)
SEARCH($SearchFile>>; | $1>>=vLintArray{$i};*)
End for
SEARCH($SearchFile>>)
CREATE SET($SearchFile>>;"Relating")
UNION("Related";"Relating";"Related")
`Progress(1) `update thermometer
End for
CLEAR VARIABLE(vLIntArray)
Else
FIRST RECORD($BaseFile>>)
For ($j;1;$BaseRecs;$Max)
SEARCH($SearchFile>>;$1>>=$2>>;*)
If ($j=$LastJ)
$Max:=$BaseRecs-$j+1
End if
For ($i;2;$Max)
NEXT RECORD($BaseFile>>)
SEARCH($SearchFile>>; | $1>>=$2>>;*)
End for
SEARCH($SearchFile>>)
CREATE SET($SearchFile>>;"Relating")
UNION("Related";"Relating";"Related")
NEXT RECORD($BaseFile>>)
`Progress(1) `update thermometer
End for
End if
USE SET("Related")
CLEAR SET("Related")
CLEAR SET("Relating")
`Progress(0) `close progress indicator window
End case
Date: Thu, 3 Jun 1993 13:01:07 -0800
From: chuckp@shiva.cac.washington.edu (Chuck Pliske)
Subject: Re: Join
Bob, (and Bill) I don't have the CI$ discussions archived, but here is the
relateSelection procedure in all its glory:
Bill, re:
"In your RelateSelection/built search, do you sort the selection (or
call SELECTION TO ARRAY, then SORT ARRAY) in order to avoid searching
for the same value twice?"
No, no sorting, just built searches, for every 250 records of the "input"
file we build a 250 line search command, then execute it. Note we could
become server compatible by changing the record loop to create sets of 250
records and apply to selection as in the top case, thus avoiding the "next
record" which forces the whole record to be loaded over the net uselessly.
`Procedure RelateSelection
`it's a good idea to have automatic relations off before running this proc.
gUserCancel:=False `set up exit test
ON EVENT CALL("CancelTest")
START TRANSACTION
$File1:=File(File($1)) `gets the related records in file 1 for the current
`selection of file 2
$File2:=File(File($2))
If (Records in selection($File2>)<257) `built searches don't like more than 256
$F1:=$1 `Can't directly use $1 or $2 in Apply to selection
$F2:=$2
SEARCH($File1>;$1>=$2>;*)
APPLY TO SELECTION($File2>;SEARCH($File1>; | $F1>=$F2>;*))
SEARCH($File1>)
Else
CREATE EMPTY SET($file1>;"Related")
FIRST RECORD($File2>)
For ($j;1;Records in selection($File2>);250)
SEARCH($File1>;$1>=$2>;*)
MESSAGE("Matching "+Filename($File1)+" records to "+Filename($File2)+
"Records..."+Char(13)+Char(13)+String(Round($j*100/Records in
selection($File2>);0))+"%")
$limit:=Lessor (Records in selection($File2>)-Selected record
number($file2>);250)
For ($i;1;$limit)
SEARCH($File1>; | $1>=$2>;*)
NEXT RECORD($File2>)
End for
SEARCH($File1>)
CREATE SET($File1>;"Relating")
UNION("Related";"Relating";"Related")
If (gUserCancel)
$i:=Records in selection($File2>)+1
End if
End for
USE SET("Related")
CLEAR SET("Related")
CLEAR SET("Relating")
End if
CANCEL TRANSACTION
ON EVENT CALL("")